﻿using MongoDB.Driver;
using Sustainalytics.Synchronization.Interface;
using Sustainalytics.Entities;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace Sustainalytics.ClientDW.Synchronization.SyncESGData.RPIndicatorExtendedLogic
{
    public class CompanyHistoricalDataIndicatorsQuery
    {
        private readonly IMongoCollection<CompanyHistoricalDataIndicators> mongoCollection;
        private readonly ILogger logger;
        private DateTime processedDate;

        public CompanyHistoricalDataIndicatorsQuery(IMongoCollection<CompanyHistoricalDataIndicators> mongoCollection, ILogger logger)
        {
            this.mongoCollection = mongoCollection;
            this.logger = logger;
        }

        public async Task<CompanyHistoricalDataIndicatorsDictionary> Get()
        {
            var currentDate = DateTime.UtcNow.Date;
            processedDate = new DateTime(currentDate.Year, currentDate.Month, 1).AddMonths(-12).ToLocalTime();

            var stopWatch = Stopwatch.StartNew();
            var indicators = await mongoCollection.Find(x => x.ProcessedDate == processedDate).ToListAsync();
            var result = indicators.GroupBy(x => x.CompanyId).Select(x => x.Last())
                    .ToDictionary(hdi => hdi.CompanyId,
                        hdi => hdi.Indicators.ToDictionary(i => i.IndicatorNumber, i => i.RawScore));

            logger.Log($"Received {result.Count} historicacl indicators data from the database (duration {stopWatch.Elapsed})");

            return new CompanyHistoricalDataIndicatorsDictionary() { result };
        }
    }

    public class CompanyHistoricalDataIndicatorsDictionary : IDictionary<Guid, Dictionary<string, int?>>
    {
        private IDictionary<Guid, Dictionary<string, int?>> dictionary = new Dictionary<Guid, Dictionary<string, int?>>();

        public CompanyHistoricalDataIndicatorsDictionary Add(IDictionary<Guid, Dictionary<string, int?>> value)
        {
            dictionary = value;
            return this;
        }

        public IEnumerator<KeyValuePair<Guid, Dictionary<string, int?>>> GetEnumerator()
        {
            return dictionary.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public void Add(KeyValuePair<Guid, Dictionary<string, int?>> item)
        {
            dictionary.Add(item.Key, item.Value);
        }

        public void Clear()
        {
            dictionary.Clear();
        }

        public bool Contains(KeyValuePair<Guid, Dictionary<string, int?>> item)
        {
            return dictionary.Contains(item);
        }

        public void CopyTo(KeyValuePair<Guid, Dictionary<string, int?>>[] array, int arrayIndex)
        {
            dictionary.CopyTo(array, arrayIndex);
        }

        public bool Remove(KeyValuePair<Guid, Dictionary<string, int?>> item)
        {
            return dictionary.Remove(item);
        }

        public int Count => dictionary.Count;
        public bool IsReadOnly => dictionary.IsReadOnly;

        public bool ContainsKey(Guid key)
        {
            return dictionary.ContainsKey(key);
        }

        public void Add(Guid key, Dictionary<string, int?> value)
        {
            dictionary.Add(key, value);
        }

        public bool Remove(Guid key)
        {
            return dictionary.Remove(key);
        }

        public bool TryGetValue(Guid key, out Dictionary<string, int?> value)
        {
            return dictionary.TryGetValue(key, out value);
        }

        public Dictionary<string, int?> this[Guid key]
        {
            get { return dictionary[key]; }
            set { dictionary[key] = value; }
        }

        public ICollection<Guid> Keys => dictionary.Keys;

        public ICollection<Dictionary<string, int?>> Values => dictionary.Values;
    }
}
